package controllers

import (
	"fmt"
	"github.com/XieWeikai/PlaceToGo/models"
	"github.com/XieWeikai/PlaceToGo/utils"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"strconv"
)

var userKeyMap = map[string]string{
	"creationTime": "created_at",
	"updateTime":   "updated_at",
	"userType":     "user_type",
	"idType":       "identity_type",
	"idNumber":     "identity_number",
	"userProfile":  "user_intro",
	"userLevel":    "user_level",
}

func GetUser(c *gin.Context) {
	var u models.User
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid user id"})
		return
	}
	u.ID = uint(id)
	if _, err := u.GetFirst(); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	log.Println("returning user", u)
	c.JSON(http.StatusOK, &u)
}

func GetUsers(c *gin.Context) {
	filter, err := utils.ParseFilter(c.DefaultQuery("filter", "{}"))
	filter = utils.ReplaceKeys(filter, userKeyMap)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	l, r, err := utils.ParseRange(c.DefaultQuery("range", "[0, 9]"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	sortBy, sortOrder, err := utils.ParseSort(c.DefaultQuery("sort", "[\"id\", \"asc\"]"))
	sortBy = userKeyMap[sortBy]
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	users, cnt, err := models.GetUsers(filter, int(r-l+1), int(l), sortBy, sortOrder)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.Header("Content-Range", fmt.Sprintf("users %d-%d/%d", l, r, cnt))
	c.JSON(http.StatusOK, users)
}

func UpdateUser(c *gin.Context) {
	var u models.User
	updateUid, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid user id"})
		return
	}
	uid := c.MustGet("user_id").(uint)
	utype := c.MustGet("user_type").(string)
	if utype != models.ADMIN && uint(updateUid) != uid {
		c.JSON(http.StatusForbidden, gin.H{"error": "you can only update your own profile"})
		return
	}

	u.ID = uint(updateUid)
	dto := models.UpdateUserDTO{}

	if c.ShouldBindJSON(&dto) != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"})
		return
	}

	if err := u.UpdateById(&dto); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, &u)
}
